using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using StaffWarsFm.Lib.Data;
using StaffWarsFm.Properties;

namespace StaffWarsFm.Discovery
{
    public class ServicePublisher
    {
        private static ServicePublisher instance;

        public static ServicePublisher Instance
        {
            get { return instance; }
            set { instance = value; }
        }

        private bool publishing;
        private UdpClient client;
        private string hostName;
        private User user;
        private IPAddress multicastGroupIp;
        private Thread publishingThread;

        public void Start(string hostName, User user)
        {
            if (publishing) throw new InvalidOperationException("Already publishing service");
            if (hostName == null) throw new ArgumentNullException("hostname");
            if (user == null) throw new ArgumentNullException("user");

            this.hostName = hostName;
            this.user = user;

            client = new UdpClient(
                Settings.Default.DiscoveryMulticastGroupPort,
                AddressFamily.InterNetwork
                );

            multicastGroupIp = IPAddress.Parse(Settings.Default.DiscoveryMulticastGroupAddress);
            client.JoinMulticastGroup(multicastGroupIp);

            publishingThread = new Thread(Publish);

            publishingThread.Start();

            publishing = true;
        }

        public void Stop()
        {
            if (!publishing) throw new InvalidOperationException("The service isn't running");

            publishingThread.Abort();

            client.DropMulticastGroup(multicastGroupIp);
            client.Close();
        }

        private void Publish()
        {
            while (true)
            {
                IPEndPoint clientEndPoint = null;
                var requestData = client.Receive(ref clientEndPoint);
                var requestText = Encoding.UTF8.GetString(requestData);

                if (requestText != DiscoverCommands.FIND_SPEAKER_MASTER)
                    continue;

                Debug.WriteLine(string.Format("Responding to {0}", clientEndPoint.Address));

                // Respond with the host name
                var responseText = string.Format(
                    "{1}{0}{2}{0}{3}",
                    Environment.NewLine,
                    hostName,
                    user.UserName,
                    user.DisplayName
                    );

                var responseData = Encoding.UTF8.GetBytes(responseText);

                // Open a response to the client on the response
                var responseClient = new UdpClient();
                responseClient.Connect(clientEndPoint.Address, Settings.Default.DiscoveryReplyPort);
                responseClient.Send(responseData, responseData.Length);
                responseClient.Close();
            }
        }
    }
}